/*
 * Copyright ThinkTank Maths Limited 2006 - 2008
 *
 * This file is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This file is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this file. If not, see <http://www.gnu.org/licenses/>.
 */
package com.openlapi;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.bluetooth.RemoteDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import thinktank.j2me.BluetoothDeviceDiscover;
import thinktank.j2me.TTUtils;
import thinktank.j2me.TTWebUtils;
import thinktank.j2me.TTUtils.ILogger;

/**
 * Standalone MIDlet that connects to and logs connections from a GPS device over
 * bluetooth to a remote webserver. Not a part of the OpenLAPI jar file.
 * <p>
 * Copy the following code into a file on a php-enabled webserver, giving write access to
 * the webserver on a file named "nmea.log" and this MIDlet will allow for remote logging.
 * Edit the variable {@link #HTTP_POST_LOGGER} to point to your server.
 * 
 * <pre><code>
 * &lt;?php
 *  $file = &quot;nmea.log&quot;;
 *  $nmea = $_POST[&quot;nmea&quot;];
 *  if (strlen($nmea) &gt; 0){
 *  // post mode
 *  $fh = fopen($file, 'w') or die(&quot;can't open file&quot;);
 *  fwrite($fh, $nmea);
 *  fclose($fh);
 *  } else {
 *  // read log mode
 *  header(&quot;Content-type: text/plain&quot;);
 *  $filesize = filesize($file);
 *  if ($filesize &gt; 0){
 *  $fh = fopen($file, 'r');
 *  $nmea = fread($fh, $filesize);
 *  fclose($fh);
 *  echo $nmea;
 *  }
 *  }
 *  ?&gt;
 * </code></pre>
 * 
 * @author Samuel Halliday, ThinkTank Maths Limited
 */
public class NMEALogger extends MIDlet {
	// sentences to record
	public static final int SENTENCE_COUNT = 100;

	// Edit this to point to your web server logger
	public final String HTTP_POST_LOGGER = "http://fommil.me.uk/nmea.php";

	private final Form form;

	/**
	 * @throws IOException
	 */
	public NMEALogger() throws IOException {
		form = new Form("NMEA Logger");
		TTUtils.registerLogger(new ILogger() {
			public void log(String message) {
				form.append(message);
				Display.getDisplay(NMEALogger.this).setCurrent(form);
			}
		});
	}

	private InputStream connectToDevice(RemoteDevice device) throws IOException {
		// make the connection and receive the InputStream
		String uri =
				"btspp://" + device.getBluetoothAddress()
						+ ":1;authenticate=false;master=false;encrypt=false";
		TTUtils.log("URI: " + uri);
		StreamConnection con =
				(StreamConnection) Connector.open(uri, Connector.READ);
		InputStream stream = con.openInputStream();
		return stream;
	}

	/**
	 * @return
	 */
	private InputStream discoverAndConnect() {
		BluetoothDeviceDiscover discover = new BluetoothDeviceDiscover();
		// this will block for about 10 to 20 seconds
		// we may wish to rewrite this to run in another thread
		// but then we won't be able to report failures here
		Hashtable devices = discover.discover();
		Enumeration names = devices.keys();
		InputStream input = null;
		while (names.hasMoreElements()) {
			String name = (String) names.nextElement();
			TTUtils.log("Seen " + name);
			if (name.indexOf("GPS") != -1)
				try {
					TTUtils.log("connecting to " + name);
					input = connectToDevice((RemoteDevice) devices.get(name));
					break;
				} catch (IOException e) {
					// if we fail to connect... maybe there is another device
					TTUtils.log("IOException " + e.getMessage());
				}
		}
		return input;
	}

	protected void destroyApp(boolean force) throws MIDletStateChangeException {
	}

	protected void pauseApp() {
	}

	protected void startApp() throws MIDletStateChangeException {
		Display.getDisplay(this).setCurrent(form);
		InputStream input = null;
		for (int i = 0; i < 5; i++) {
			TTUtils.log("Discovering bluetooth GPS devices...");
			input = discoverAndConnect();
			if (input != null)
				break;
		}
		if (input == null) {
			TTUtils.log("Didn't connect. Exiting.");
			return;
		}
		StringBuffer sentence = new StringBuffer();
		StringBuffer all = new StringBuffer();
		int i;
		int count = 0;
		try {
			while (((i = input.read()) != -1) && (count < SENTENCE_COUNT)) {
				char c = (char) i;
				sentence.append(c);
				if (c == '\n') {
					count++;
					all.append(sentence);
					form.append(".");
					Display.getDisplay(this).setCurrent(form);
					sentence = new StringBuffer();
				}
			}
			input.close();
		} catch (IOException e) {
			TTUtils.log("IOException " + e.getMessage());
		}

		// now attempt to upload the NMEA to a web server using HTTP POST
		Hashtable table = new Hashtable();
		table.put("nmea", all);
		try {
			TTWebUtils.httpPost(HTTP_POST_LOGGER, table);
		} catch (IOException e) {
			TTUtils.log("IOException in upload " + e.getMessage());
		}
	}
}
